<template>
  <el-dialog
    title="菜单关联角色"
    :visible.sync="visible"
    width="50%"
    top="10vh"
    :before-close="closeDialogHandle"
    :close-on-click-modal="false"
    class="menu-role-dialog">
    <el-form inline size="mini" label-width="70px">
      <el-form-item label="菜单名称">
        <el-input :value="menu.name" readonly></el-input>
      </el-form-item>
    </el-form>
    <el-row v-loading="dataLoad" :gutter="20" class="role-box">
      <el-col :span="12">
        <el-card>
          <div slot="header">
            <span>可关联角色</span>
          </div>
          <div class="search-box">
            <el-input v-model="roleFilterText" clearable size="mini" placeholder="检索可关联角色" @input="roleFilterHandle(300)"></el-input>
          </div>
          <div class="role-list">
            <div v-for="role in showRoleList" :key="'no' + role.roleId" class="role">
              <span >{{role.roleName}}</span>
              <span class="simple-name">{{role.roleKey}}</span>
              <span class="simple-name">{{role.deptName}}</span>
              <i v-show="role.newRelation" @click="addRoleHandle(role)" class="el-icon-plus role-btn" :class="{ 'disabled': buttonLoad }"></i>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :span="12">
        <el-card>
          <div slot="header">
            <span>已关联角色</span>
          </div>
          <div class="search-box">
            <el-input v-model="menuRoleFilterText" clearable size="mini" placeholder="检索已关联角色" @input="menuRoleFilterHandle(300)"></el-input>
          </div>
          <div class="role-list">
            <div v-for="role in showMenuRoleList" :key="'yes' + role.roleId" class="role">
              <span :class="{ 'new-role': role.newRelation }">{{role.roleName}}</span>
              <span class="simple-name">{{role.roleKey}}</span>
              <span class="simple-name">{{role.deptName}}</span>
              <i @click="subRoleHandle(role)" class="el-icon-minus role-btn" :class="{ 'disabled': buttonLoad }"></i>
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>
    <span slot="footer">
      <el-button @click="closeDialogHandle">关 闭</el-button>
      <el-button :disabled="dataLoad || buttonLoad" type="primary" @click="submitHandle">确 定</el-button>
    </span>
  </el-dialog>
</template>

<script>
  export default {
    name: "menu-role-relation-dialog",
    data() {
      return {
        // 弹出框显示状态[true-显示 false-隐藏]
        visible: false,
        // 菜单对象
        menu: {
          // 菜单主键
          menuId: undefined,
          // 菜单名称
          name: undefined,
        },
        // 可关联的角色列表
        roleList: [],
        // 可关联的角色列表（页面显示）
        showRoleList: [],
        // 菜单已关联的角色列表
        menuRoleList: [],
        // 菜单已关联的角色列表（页面显示）
        showMenuRoleList: [],
        // 可关联角色检索内容
        roleFilterText: '',
        // 可关联角色检索定时器
        roleFilterTimer: undefined,
        // 菜单已关联的角色检索内容
        menuRoleFilterText: '',
        // 菜单已关联的角色检索定时器
        menuRoleFilterTimer: undefined,
        // 数据加载状态[true-加载中 false-未加载]
        dataLoad: false,
        // 按钮禁用状态[true-禁用 false-可点击]
        buttonLoad: false
      }
    },
    methods: {
      /**
       *
       * @param menu
       */
      initDialog(menu) {
        // 打开弹出框
        this.visible = true;

        this.menu.menuId = menu.menuId;
        this.menu.name = menu.name;

        this.getMenuRoleRelationData(menu.menuId);
      },
      /**
       * 获取菜单关联角色相关数据方法
       * @param {string} menuId 菜单主键
       */
      getMenuRoleRelationData(menuId) {
        // 加载数据
        this.dataLoad = true;
        this.$axios.$get('/sys/role-menu/relation/data', { params: { menuId }})
          .then(({ data }) => {
            this.roleList = data.roleList;
            this.showRoleList = data.roleList;
            for (let role of data.roleList) {
              this.$set(role, 'newRelation', true);
            }
            this.menuRoleList = data.menuRoleList;
            this.showMenuRoleList = data.menuRoleList;
            for (let role of data.menuRoleList) {
              this.$set(role, 'newRelation', false);
            }
          })
          .catch(() => {})
          .finally(() => {
            // 加载结束
            this.dataLoad = false;
          })
      },
      /**
       * 提交菜单关联角色事件
       */
      submitHandle() {
        // 按钮禁用
        this.buttonLoad = true;
        let data = {
          menuId: this.menu.menuId,
          roleIdList: this.menuRoleList.map(_role => _role.roleId)
        }
        this.$axios.$post('/sys/role-menu/modify', data)
          .then(() => {
            this.notify('success', '操作成功', `修改’${this.menu.name}‘菜单关联角色成功`);

            this.closeDialogHandle();
          })
          .catch(() => {})
          .finally(() => {
            // 按钮恢复可使用
            this.buttonLoad = false;
          })
      },
      /**
       * 可关联角色检索事件
       * @param {number} timeout 延时时长
       */
      roleFilterHandle(timeout) {
        clearTimeout(this.roleFilterTimer);
        this.roleFilterTimer = setTimeout(() => {
          let roleFilterText = this.roleFilterText;
          if (!roleFilterText) {
            this.showRoleList = this.roleList;
          } else {
            this.showRoleList = this.roleList.filter(role => role.roleName.indexOf(roleFilterText) !== -1
              || role.simpleName.indexOf(roleFilterText) !== -1
              || role.deptName.indexOf(roleFilterText) !== -1);
          }
          clearTimeout(this.roleFilterTimer);
        }, timeout);
      },
      /**
       * 已关联角色检索事件
       * @param {number} timeout 延时时长
       */
      menuRoleFilterHandle(timeout) {
        clearTimeout(this.menuRoleFilterTimer);
        this.menuRoleFilterTimer = setTimeout(() => {
          let menuRoleFilterText = this.menuRoleFilterText;
          if (!menuRoleFilterText) {
            this.showMenuRoleList = this.menuRoleList;
          } else {
            this.showMenuRoleList = this.menuRoleList.filter(role => role.roleName.indexOf(menuRoleFilterText) !== -1
              || role.simpleName.indexOf(menuRoleFilterText) !== -1
              || role.deptName.indexOf(menuRoleFilterText) !== -1);
          }
          clearTimeout(this.menuRoleFilterTimer);
        }, timeout);
      },
      /**
       * 增加菜单关联角色事件
       * @param {Object} role 角色对象
       */
      addRoleHandle(role) {
        // 按钮禁用
        this.buttonLoad = true;
        let menuRoleList = this.menuRoleList;
        if (menuRoleList.some(_role => _role.roleId === role.roleId)) {
          // 可关联角色列表存储的角色对象变为’不可关联‘状态
          role.newRelation = false;
          this.notify('', '温馨提示', `菜单已关联${role.roleName}，不可重复关联`)
          // 按钮恢复可使用
          this.buttonLoad = false;
          return;
        }
        // 新增用户关联的角色
        menuRoleList.unshift(role);
        // 更新显示的已关联角色列表
        this.menuRoleFilterHandle(0)

        this.roleList = this.roleList.filter(_role => _role.roleId !== role.roleId);
        this.showRoleList = this.showRoleList.filter(_role => _role.roleId !== role.roleId);

        // 按钮恢复可使用
        this.buttonLoad = false;
      },
      /**
       * 减少菜单关联角色事件
       * @param {Object} role 角色对象
       */
      subRoleHandle(role) {
        // 按钮禁用
        this.buttonLoad = true;

        let roleList = this.roleList;
        let _role = roleList.find(_role => _role.roleId === role.roleId);
        if (_role) {
          /*
            可关联角色列表和已关联角色列表同时存在该角色
            可关联角色列表存储的角色对象变为’可关联‘状态
           */
          _role.newRelation = true;
        } else {
          role.newRelation = true;
          // 已关联角色列表 转移到 可关联角色列表
          roleList.unshift(role);
          // 更新显示的可关联角色列表
          this.roleFilterHandle(0)
        }
        // 减少菜单关联的角色
        this.menuRoleList = this.menuRoleList.filter(_role => _role.roleId !== role.roleId);
        this.showMenuRoleList = this.showMenuRoleList.filter(_role => _role.roleId !== role.roleId);

        // 按钮恢复可使用
        this.buttonLoad = false;
      },
      /**
       * 关闭弹出框事件
       */
      closeDialogHandle() {
        // 关闭弹出框
        this.visible = false;
        this.menu = {
          menuId: undefined,
          name: undefined
        }
        // 可关联的角色列表
        this.roleList = [];
        // 可关联的角色列表（页面显示）
        this.showRoleList = [];
        // 菜单已关联的角色列表
        this.menuRoleList = [];
        // 菜单已关联的角色列表（页面显示）
        this.showMenuRoleList = [];
        // 可关联角色检索内容
        this.roleFilterText = '';
        // 可关联角色检索定时器
        clearTimeout(this.roleFilterTimer);
        this.roleFilterTimer = undefined;
        // 菜单已关联的角色检索内容
        this.menuRoleFilterText = '';
        clearTimeout(this.menuRoleFilterTimer);
        // 菜单已关联的角色检索定时器
        this.menuRoleFilterTimer = undefined;
      }
    }
  }
</script>

<style scoped>
  .menu-role-dialog >>> .el-dialog__body {
    padding: 10px 20px;
  }
  .role-box >>> .el-card__header {
    padding: 10px 20px;
  }
  .role-box .search-box {
    margin-bottom: 10px;
    width: 60%;
  }
  .role-box .role-list {
    height: 350px;
    max-height: 350px;
    overflow-y: scroll;
  }
  .role-box .role-list .role {
    line-height: 30px;
    position: relative;
  }
  .role-box .role-list .role .new-role {
    color: #71e2a3;
  }
  .role-box .role-list .role .simple-name {
    color: #C0C4CC;
  }
  .role-box .role-list .role .role-btn {
    position: absolute;
    right: 10px;
    cursor: pointer;
    font-size: 17px;
    line-height: 30px;
  }
  .role-box .role-list .role .role-btn.disabled {
    pointer-events: none;
  }
  .role-box .role-list .role-item .role-btn:hover {
    color: #71e2a3;
  }
</style>
